home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Info-Mac 3
/
Info_Mac_1994-01.iso
/
Applications
/
Welcome 1.3.1
/
Welcome.c
< prev
next >
Wrap
Text File
|
1993-08-25
|
16KB
|
593 lines
/* Welcome!
Welcome is an recreation of the Welcome2 application using the new Speech Manager.
I have no connection with the original author, except fond memories. :-)
Copyright 1993 by Garrett Fitzgerald
A product of donnael Software
v1.3 - Menu selection of future default voice works! - 8/25/93
v1.2 - Show speaking voice - 8/22/93
Error alerts
Gestalt now works, with inclusion of <GestaltEqu.h>
Lists voices
Added about box
Defaults to "Female Voice", if available
v1.1.1 - Increased app partition to permit more complicated voices - 8/16/93
Changed to StopSpeechAt end of word
Added commas after weekday
Re-did Finder icon
v1.1 - Added WaitNextEvent to allow quitting - 8/16/93
v1.0 - initial release - 8/15/93
*/
#include "Welcome.h"
short vol_refnum,
prefs_file_refnum;
/* toolbox_init()
Initializes the full toolbox--things here seem to depend on it.
*/
toolbox_init()
{
InitGraf(&thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(nil);
InitCursor();
}
/* prefs_init()
Finds the Welcome! preferences file, or creates a new one. Returns true if file
exists, false if the prefs folder can't be found or the file can't be opened.
*/
Boolean
prefs_init()
{
OSErr err;
StringHandle vol_name;
long prefs_dir;
FSSpec prefs_spec;
Handle voice_res;
VoiceSpec init_voice_res;
extern short prefs_file_refnum,
vol_refnum;
vol_name = NewString("\p");
err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder,
&vol_refnum, &prefs_dir);
if (err != noErr)
return false;
err = FSMakeFSSpec(vol_refnum, prefs_dir, PREFS_FILE_NAME, &prefs_spec);
if (err == fnfErr) {
FSpCreateResFile(&prefs_spec, 'GSFC', 'pref', smSystemScript);
err = ResError();
if (err != noErr) {
FSpDelete(&prefs_spec);
return false;
}
prefs_file_refnum = FSpOpenResFile(&prefs_spec, fsRdWrPerm);
err = ResError();
if (err != noErr) {
FSpDelete(&prefs_spec);
return false;
}
init_voice_res.creator = '????';
init_voice_res.id = '????';
PtrToHand((Ptr)&init_voice_res, &voice_res, sizeof(VoiceSpec));
AddResource(voice_res, VOICE_RES_TYPE, VOICE_RES_NUMB, "\pPreferred voice");
WriteResource(voice_res);
FlushVol(*vol_name, vol_refnum);
}
else {
prefs_file_refnum = FSpOpenResFile(&prefs_spec, fsRdWrPerm);
err = ResError();
if (err != noErr) {
return false;
}
}
}
/* date_to_text()
Converts the numbers returned in Secs2Date to more readable months, days, time, and
days of the week.
*/
void
date_to_text(StringHandle *month, StringHandle *day, StringHandle *weekday,
StringHandle *time, StringHandle *greeting)
{
long secs,
mil_time;
Str255 hmin;
DateTimeRec now;
GetDateTime(&secs);
IUTimeString(secs, false, hmin); /* 4:22 AM */
*(hmin+*hmin+1) = '%'; /* Stick in a % for Munger to find later */
*hmin += 1; /* and fix the length byte... */
*time = NewString(hmin);
mil_time = Munger(time, 5, "M", 1, ".M.", 3); /* If this is 12 hour time, change */
if (mil_time >= 0) /* AM/PM to A.M./P.M. */
**time += 2; /* Length byte again... */
Secs2Date(secs, &now); /* Turn the seconds since 1904 into a date/time record */
switch (now.dayOfWeek) { /* Change the day of week, month, and date into words */
case 1:
*weekday = NewString("\pSunday, %"); /* and stick in a % for Munger to find later... */
break;
case 2:
*weekday = NewString("\pMonday, %");
break;
case 3:
*weekday = NewString("\pTuesday, %");
break;
case 4:
*weekday = NewString("\pWednesday, %");
break;
case 5:
*weekday = NewString("\pThursday, %");
break;
case 6:
*weekday = NewString("\pFriday, %");
break;
case 7:
*weekday = NewString("\pSaturday, %");
break;
}
switch (now.month) {
case 1:
*month = NewString("\pJanuary %");
break;
case 2:
*month = NewString("\pFebruary %");
break;
case 3:
*month = NewString("\pMarch %");
break;
case 4:
*month = NewString("\pApril %");
break;
case 5:
*month = NewString("\pMay %");
break;
case 6:
*month = NewString("\pJune %");
break;
case 7:
*month = NewString("\pJuly %");
break;
case 8:
*month = NewString("\pAugust %");
break;
case 9:
*month = NewString("\pSeptember %");
break;
case 10:
*month = NewString("\pOctober %");
break;
case 11:
*month = NewString("\pNovember %");
break;
case 12:
*month = NewString("\pDecember %");
break;
}
switch (now.day) {
case 1:
*day = NewString("\pfirst %");
break;
case 2:
*day = NewString("\psecond %");
break;
case 3:
*day = NewString("\pthird %");
break;
case 4:
*day = NewString("\pfourth %");
break;
case 5:
*day = NewString("\pfifth %");
break;
case 6:
*day = NewString("\psixth %");
break;
case 7:
*day = NewString("\pseventh %");
break;
case 8:
*day = NewString("\peighth %");
break;
case 9:
*day = NewString("\pnineth %");
break;
case 10:
*day = NewString("\ptenth %");
break;
case 11:
*day = NewString("\peleventh %");
break;
case 12:
*day = NewString("\ptwelveth %");
break;
case 13:
*day = NewString("\pthirteenth %");
break;
case 14:
*day = NewString("\pfourteenth %");
break;
case 15:
*day = NewString("\pfifteenth %");
break;
case 16:
*day = NewString("\psixteenth %");
break;
case 17:
*day = NewString("\pseventeenth %");
break;
case 18:
*day = NewString("\peighteenth %");
break;
case 19:
*day = NewString("\pnineteenth %");
break;
case 20:
*day = NewString("\ptwentieth %");
break;
case 21:
*day = NewString("\ptwenty-first %");
break;
case 22:
*day = NewString("\ptwenty-second %");
break;
case 23:
*day = NewString("\ptwenty-third %");
break;
case 24:
*day = NewString("\ptwenty-fourth %");
break;
case 25:
*day = NewString("\ptwenty-fifth %");
break;
case 26:
*day = NewString("\ptwenty-sixth %");
break;
case 27:
*day = NewString("\ptwenty-seventh %");
break;
case 28:
*day = NewString("\ptwenty-eighth %");
break;
case 29:
*day = NewString("\ptwenty-ninth %");
break;
case 30:
*day = NewString("\pthirtieth %");
break;
case 31:
*day = NewString("\pthirty-first %");
break;
}
/* Go though and look for holidays -- specific date */
if ((now.month == 1) & (now.day == 1))
*greeting = NewString("\pHappy New Year! %");
else if ((now.month == 2) & (now.day == 14))
*greeting = NewString("\pHappy Valentine's Day! %");
else if ((now.month == 3) & (now.day == 17))
*greeting = NewString("\pHappy Saint Patrick's Day! %");
else if ((now.month == 3) & (now.day == 19))
*greeting = NewString("\pHappy Saint Joseph's Day! %"); /* I want a zeppola! */
else if ((now.month == 6) & (now.day == 14))
*greeting = NewString("\pHappy Flag Day! %");
else if ((now.month == 7) & (now.day == 4))
*greeting = NewString("\pHappy Independence Day! %");
else if ((now.month == 10) & (now.day == 12))
*greeting = NewString("\pHappy Columbus Day! %");
else if ((now.month == 11) & (now.day == 11))
*greeting = NewString("\pHappy Veterans Day! %");
else if ((now.month == 12) & (now.day == 25))
*greeting = NewString("\pMerry Chrismas! %");
/* Now find 2nd Monday, 4th Thursday, etc. */
else if ((now.month == 2) & (now.day >= 9) & (now.day <= 15) & (now.dayOfWeek = 2))
*greeting = NewString("\pHappy Presidents' Day! %");
else if ((now.month == 5) & (now.day >= 8) & (now.day <= 14) & (now.dayOfWeek = 1))
*greeting = NewString("\pHappy Mother's Day! %");
else if ((now.month == 6) & (now.day >= 15) & (now.day <= 21) & (now.dayOfWeek = 1))
*greeting = NewString("\pHappy Father's Day! %");
else if ((now.month == 9) & (now.day >= 1) & (now.day <= 7) & (now.dayOfWeek = 2))
*greeting = NewString("\pHappy Labor Day! %");
else if ((now.month == 11) & (now.day >= 22) & (now.day <= 28) & (now.dayOfWeek = 5))
*greeting = NewString("\pHappy Thanksgiving! %");
/* Evening before holidays... */
else if ((now.month == 12) & (now.day == 31) & (now.hour >= 18))
*greeting = NewString("\pit's New Year's Eve! %");
else if ((now.month == 12) & (now.day == 25) & (now.hour >= 18))
*greeting = NewString("\pit's Chrismas Eve! %");
/* If it's not a holiday, then... */
else if ((now.hour >= 0) & (now.hour <= 4))
*greeting = NewString("\pyou should be in bed! %");
else if ((now.hour >= 5) & (now.hour <= 11))
*greeting = NewString("\pgood morning. %");
else if ((now.hour >= 12) & (now.hour <= 17))
*greeting = NewString("\pgood afternoon. %");
else if ((now.hour >= 18) & (now.hour <= 23))
*greeting = NewString("\pgood evening. %");
}
Boolean
handle_menus(long menu_choice, Boolean prefs)
{
static int checked_voice = 0;
short menu,
choice;
Str255 da_name;
MenuHandle voice_menu;
VoiceSpec voice;
Handle voice_res,
voice_hand;
OSErr err;
menu = HiWord(menu_choice);
choice = LoWord(menu_choice);
switch (menu) {
case MENU_APPLE:
switch (choice) {
case 1: /* About Branagh */
Alert(ALRT_ABOUT, nil);
break;
default: /* DAs */
GetItem(GetMHandle(MENU_APPLE), choice, da_name);
OpenDeskAcc(da_name);
break;
}
break;
case MENU_FILE:
if (choice == FILE_QUIT)
return true;
break;
case MENU_VOICES:
if ((prefs = true) && (choice != 0)) {
voice_menu = GetMHandle(MENU_VOICES);
if (checked_voice != 0)
CheckItem(voice_menu, checked_voice, false);
CheckItem(voice_menu, choice, true);
GetIndVoice(choice, &voice);
voice_res = GetResource(VOICE_RES_TYPE, VOICE_RES_NUMB);
PtrToXHand((Ptr)&voice, voice_res, sizeof(VoiceSpec));
ChangedResource(voice_res);
err = ResError();
if (err != noErr)
SysBeep(20);
}
break;
}
return false;
}
stop_speech(SpeechChannel channel)
{
OSErr err;
err = StopSpeechAt(channel, kEndOfWord);
if (err != noErr)
SysBeep(20);
while (SpeechBusy() > 0);
}
main()
{
long info,
ticks,
menu_choice;
int i;
Boolean done = false,
prefs;
EventRecord choice;
short index;
StringHandle month,
day,
weekday,
time,
greeting,
text;
OSErr err;
VoiceSpec voice;
VoiceDescription voice_info;
SpeechChannel channel;
DialogPtr voice_dlog;
Handle menu_bar,
default_voice;
MenuHandle menu,
voice_menu;
Point where;
WindowPtr which_window;
Boolean galatea = false;
extern short prefs_file_refnum,
vol_refnum;
toolbox_init();
FlushEvents(everyEvent, 0);
prefs = prefs_init();
menu_bar = GetNewMBar(MENU_BAR); /* Set up menus... */
if (menu_bar == nil) {
SysBeep(20);
return;
}
else
SetMenuBar(menu_bar);
menu = GetMHandle(MENU_APPLE);
AddResMenu(menu, 'DRVR');
err = Gestalt(gestaltSpeechAttr, &info);
if (err == gestaltUndefSelectorErr) {
ParamText("\pWelcome! requires that the Speech Manager be installed. Sorry.", "\p", "\p", "\p");
StopAlert(ALRT_ERR, nil);
SysBeep(20);
return;
}
else if (err != noErr) {
ParamText("\pProblem calling Gestalt: exiting.", "\p", "\p", "\p");
StopAlert(ALRT_ERR, nil);
SysBeep(20);
return;
}
if (!(info && (1L << gestaltSpeechMgrPresent))) {
ParamText("\pWelcome! requires that the Speech Manager be installed. Sorry.", "\p", "\p", "\p");
StopAlert(ALRT_ERR, nil);
SysBeep(20);
return;
}
err = CountVoices(&index); /* How many voices do we have? */
if (err != noErr) {
ParamText("\pI really don't think there should have been an error here...", "\p", "\p", "\p");
StopAlert(ALRT_ERR, nil);
SysBeep(20);
return;
}
voice_menu = GetMHandle(MENU_VOICES);
for (i = 1; i <= index; i++) {
err = GetIndVoice(i, &voice);
if (err != noErr) {
ParamText("\pCouldn't find indicated voice. Exiting.", "\p", "\p", "\p");
StopAlert(ALRT_ERR, nil);
SysBeep(20);
return;
}
GetVoiceDescription(&voice, &voice_info, sizeof(VoiceDescription));
AppendMenu(voice_menu, voice_info.name);
if ((voice.creator == 'gala') && (voice.id == 12)) /* If "Female voice" is available,*/
galatea = true; /* use it, unless overruled */
}
DrawMenuBar();
default_voice = GetResource(VOICE_RES_TYPE, VOICE_RES_NUMB);
HLock(default_voice);
if (((VoiceSpec *)*default_voice)->creator != '????') {
voice.creator = ((VoiceSpec *)*default_voice)->creator;
voice.id = ((VoiceSpec *)*default_voice)->id;
GetVoiceDescription(&voice, &voice_info, sizeof(VoiceDescription));
galatea = false;
}
HUnlock(default_voice);
if (galatea) {
voice.creator = 'gala';
voice.id = (long)12;
GetVoiceDescription(&voice, &voice_info, sizeof(VoiceDescription));
}
err = NewSpeechChannel(&voice, &channel); /* Open a SpeechChannel */
if (err == synthOpenFailed) {
ParamText("\pCould not open SpeechChannel: Try increasing the memory partition.", "\p", "\p", "\p");
StopAlert(ALRT_ERR, nil);
return;
}
else if (err != noErr) {
ParamText("\pCould not open SpeechChannel: exiting.", "\p", "\p", "\p");
StopAlert(ALRT_ERR, nil);
SysBeep(20);
return;
}
ParamText(voice_info.name, "\p", "\p", "\p");
voice_dlog = GetNewDialog(DLOG_VOICE, nil, WINDOW_IN_FRONT);
if (voice_dlog == nil) {
ParamText("\pCan't show current voice...", "\p", "\p", "\p");
StopAlert(ALRT_ERR, nil);
}
ShowWindow(voice_dlog);
DrawDialog(voice_dlog);
date_to_text(&month, &day, &weekday, &time, &greeting);
/* Plug everything into one long string... */
text = NewString("\pWelcome to Mackintosh, and %");
SetHandleSize(text, sizeof(Str255));
Munger(text, 1, "%", 1, *greeting+1, **greeting); /* Find the %, and replace it with */
**text = **text + **greeting - 1; /* the next part of the string... */
Munger(text, 1, "%", 1, "It's %", 6);
**text = **text + 5; /* Fix the length byte, ignoring the */
Munger(text, 1, "%", 1, *weekday+1, **weekday); /* length byte from the replacement string*/
**text = **text + **weekday - 1; /* (it got cut out, *weekday+1, anyway) */
Munger(text, 1, "%", 1, *month+1, **month);
**text = **text + **month - 1;
Munger(text, 1, "%", 1, *day+1, **day);
**text = **text + **day - 1;
Munger(text, 1, "%", 1, "at %", 4);
**text = **text + 3;
Munger(text, 1, "%", 1, *time + 1, **time);
**text = **text + **time - 1;
Munger(text, 1, "%", 1, ". Let's go!", 11);
**text = **text + 10;
MoveHHi(text);
HLock(text);
SpeakText(channel, (Ptr)(*text + 1), **text); /* Then speak the text through the channel */
/* we got up top... */
while(!done) {
WaitNextEvent((mDownMask | keyDownMask), &choice, 15, nil);
switch (choice.what) {
case mouseDown:
where = choice.where;
switch (FindWindow(where, &which_window)) {
case inMenuBar:
menu_choice = MenuSelect(where);
if (HiWord(menu_choice) != 0) {
done = handle_menus(menu_choice, prefs);
if (done == true)
stop_speech(channel);
}
HiliteMenu(0);
break;
default:
stop_speech(channel);
done = true;
break;
}
break;
case keyDown:
stop_speech(channel);
done = true;
break;
}
if (SpeechBusy() == 0)
done = true;
}
HUnlock(text);
DisposeSpeechChannel(channel); /* And clean up. */
DisposeDialog(voice_dlog);
DisposeHandle(month);
DisposeHandle(day);
DisposeHandle(weekday);
DisposeHandle(greeting);
DisposeHandle(text);
DisposeHandle(time);
CloseResFile(prefs_file_refnum);
FlushVol(NewString("\p"), vol_refnum);
}